import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widgets_pc/extentions/kq_extentions.dart';
import 'package:get/get.dart';

import '../expandablePageView/kq_size_reporting_widget.dart';
import '../gesture/kq_gesture_detector.dart';

/// 悬浮控件
class KqFloatingView extends StatefulWidget {
  /// [floatingWidget] 将悬浮在 [child] 之上
  final Widget child;

  /// 悬浮控件
  final Widget Function(
          double? left, double? top, bool isLeft, bool isDragging)?
      floatingWidgetBuilder;

  /// 初始位置-left
  final double? left;

  /// 初始位置-top
  final double? top;

  /// 是否可拖拽,默认true
  final bool dragAble;

  /// 是否松手后自动贴边吸附，默认true
  final bool autoSide;

  final HitTestBehavior? behavior;

  final KqFloatingViewDragDelegate? dragDelegate;

  const KqFloatingView(
      {Key? key,
      required this.child,
      this.left,
      this.top,
      this.floatingWidgetBuilder,
      this.dragDelegate,
      this.behavior,
      this.autoSide = true,
      this.dragAble = true})
      : super(key: key);

  @override
  KqFloatingViewState createState() => KqFloatingViewState();
}

class KqFloatingViewState extends State<KqFloatingView>
    with SingleTickerProviderStateMixin {
  double? left;
  double? top;

  Offset? startPos;

  Size? floatingSize;

  bool releaseIsLeft = true;
  double? releaseX;

  bool isDragging = false;

  late AnimationController _controller;

  static const Duration _sideDuration = Duration(milliseconds: 150);

  @override
  void initState() {
    widget.dragDelegate?.bind(this);
    left = widget.left ?? 0;
    top = widget.top;
    _controller = AnimationController(duration: _sideDuration, vsync: this)
      ..value = 0
      ..addListener(() {
        if (widget.autoSide) {
          setState(() {
            var value = _controller.value;
            if (releaseIsLeft) {
              // 左移
              left = (1 - value) * left!;
            } else {
              // 右移
              if (floatingSize != null && releaseX != null) {
                // 不能超出屏幕
                var maxLeft = context.width - floatingSize!.width;
                var l = value * maxLeft;
                if (l > releaseX!) {
                  left = l;
                } else if (releaseX! > maxLeft) {
                  left = maxLeft;
                }
              }
            }
          });
        }
      });
    super.initState();
  }

  @override
  void didUpdateWidget(covariant KqFloatingView oldWidget) {
    widget.dragDelegate?.bind(this);
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    widget.dragDelegate?.unBind();
    super.dispose();
  }

  Offset? parentPos;
  double width = 0;

  double height = 0;

  @override
  Widget build(BuildContext context) {
    parentPos = context.position();
    return LayoutBuilder(
      builder: (ctx, constraintType) {
        width = constraintType.maxWidth;
        height = constraintType.maxHeight;
        if (left != null) {
          left = min(left!, width - 50);
        }
        if (top != null) {
          top = min(top!, height - 50);
        }
        var isLeft =
            ((left ?? 0) + ((floatingSize?.width ?? 0) / 2)) < width / 2;
        Widget child = KqSizeReportingWidget(
          onSizeChange: (Size? value) {
            setState(() {
              floatingSize = value;
            });
          },
          child: widget.floatingWidgetBuilder == null
              ? Container()
              : widget.floatingWidgetBuilder!
                  .call(left, top, isLeft, isDragging),
        );
        if (widget.dragAble) {
          child = KqGestureDetector(
            behavior: widget.behavior,
            onDragStart: onDragStart,
            onDragEnd: onDragEnd,
            onDragUpdate: onDragUpdate,
            onDragCancel: onDragCancel,
            child: child,
          );
        }
        return Stack(
          children: [
            widget.child,
            if (widget.floatingWidgetBuilder != null)
              Positioned(left: left, top: top ?? height / 2, child: child),
          ],
        );
      },
    );
  }

  onDragCancel() {
    isDragging = false;
    startPos = null;
  }

  onDragUpdate(DragUpdateDetails details) {
    isDragging = true;
    var globalPos = details.globalPosition;
    var dx = globalPos.dx - startPos!.dx;
    var dy = globalPos.dy - startPos!.dy - (parentPos?.dy ?? 0);
    if (dx < 0) {
      dx = 0;
    }
    if (dy < 0) {
      dy = 0;
    }
    if (floatingSize != null) {
      // 不能超出屏幕
      if (dx > (width - floatingSize!.width)) {
        dx = width - floatingSize!.width;
      }
      if (dy > (height - floatingSize!.height)) {
        dy = height - floatingSize!.height;
      }
    }
    setState(() {
      left = dx;
      top = dy;
    });
  }

  onDragEnd(DragEndDetails details) {
    //自动吸附
    isDragging = false;
    if (widget.autoSide) {
      _controller.forward(from: 0);
    }
    releaseIsLeft =
        ((left ?? 0) + ((floatingSize?.width ?? 0) / 2)) < width / 2;
    releaseX = left;
    // 位置校准
  }

  onDragStart(DragStartDetails details) {
    startPos = details.localPosition;
  }
}

class KqFloatingViewDragDelegate {
  KqFloatingViewState? _state;

  bind(KqFloatingViewState state) {
    _state = state;
  }

  unBind() {
    _state = null;
  }

  onDragCancel() {
    _state?.onDragCancel();
  }

  onDragUpdate(DragUpdateDetails details) {
    _state?.onDragUpdate(details);
  }

  onDragEnd(DragEndDetails details) {
    _state?.onDragEnd(details);
  }

  onDragStart(DragStartDetails details) {
    _state?.onDragStart(details);
  }
}
